package ecs.net.systems;

import ecs.core.BaseSystem;
import ecs.net.EventType;
import ecs.net.Status;
import ecs.net.components.ServerSocketComponent;
import ecs.net.components.StatusComponent;

import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.concurrent.CompletableFuture;

public class AcceptSystem extends BaseSystem {

    public AcceptSystem() {
        super();
        interestingComponentTypes(new Class[]{ServerSocketComponent.class, StatusComponent.class});
    }

    private void startAccept() {
        if(!enable()) return;
        CompletableFuture.runAsync(() -> {
            entityComponents().forEach(components -> {
                ServerSocketComponent server = (ServerSocketComponent) components.get(0);
                StatusComponent status = (StatusComponent) components.get(1);
                if(status.status() == Status.Connected)
                {
                    try {
                        Socket socket = server.socket().accept();
                        broadcast(EventType.SocketCreate, socket);
                        startAccept();
                    } catch (SocketTimeoutException e) {
                        status.status(Status.Timeout);
                        broadcast(EventType.SocketStatusChanged, e);
                    } catch (IOException e) {
                        if (!server.socket().isClosed())
                            try {
                                server.socket().close();
                            } catch (IOException ignored) {
                            }
                        status.status(Status.Closed);
                        broadcast(EventType.SocketStatusChanged, e);
                    }
                }
            });
        });
    }

    @Override
    public void start() {
        startAccept();
    }
}
